package com.swsc.solarverse.common.mybatis;

import com.baomidou.mybatisplus.annotation.FieldStrategy;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.core.injector.AbstractMethod;
import com.baomidou.mybatisplus.core.metadata.TableFieldInfo;
import com.baomidou.mybatisplus.core.metadata.TableInfo;
import org.apache.ibatis.executor.keygen.NoKeyGenerator;
import org.apache.ibatis.mapping.MappedStatement;
import org.apache.ibatis.mapping.SqlSource;

import java.util.Objects;

/**
 * @Author chencl
 * @Date 2022/1/18 14:40
 * @Version 1.0
 * @Description InsertListMethod
 */
public class InsertListMethod extends AbstractMethod {


    @Override
    public MappedStatement injectMappedStatement(Class<?> mapperClass, Class<?> modelClass, TableInfo tableInfo) {
        final String sql = "<script>insert into %s %s values %s</script>";
        final String fieldSql = prepareFieldSql(tableInfo);
        final String valueSql = prepareValuesSqlForMysqlBatch(tableInfo);
        final String sqlResult = String.format(sql, tableInfo.getTableName(), fieldSql, valueSql);
        SqlSource sqlSource = languageDriver.createSqlSource(configuration, sqlResult, modelClass);
        return this.addInsertMappedStatement(mapperClass, modelClass, "insertList", sqlSource, new NoKeyGenerator(), null, null);
    }

    private String prepareFieldSql(TableInfo tableInfo) {
        StringBuilder fieldSql = new StringBuilder();
        if (tableInfo.getIdType() != IdType.AUTO) {
            fieldSql.append(tableInfo.getKeyColumn()).append(",");
        }
        tableInfo.getFieldList().stream()
                .filter(info -> !FieldStrategy.NEVER.equals(info.getInsertStrategy()))
                .forEach(info -> fieldSql.append(info.getColumn()).append(","));
        fieldSql.delete(fieldSql.length() - 1, fieldSql.length());
        fieldSql.insert(0, "(");
        fieldSql.append(")");
        return fieldSql.toString();
    }

    private String prepareValuesSqlForMysqlBatch(TableInfo tableInfo) {
        final StringBuilder valueSql = new StringBuilder();
        valueSql.append("<foreach collection=\"list\" item=\"item\" index=\"index\" open=\"(\" separator=\"),(\" close=\")\">");
        if (tableInfo.getIdType() != IdType.AUTO) {
            valueSql.append("#{item.").append(tableInfo.getKeyProperty()).append("},");
        }
        tableInfo.getFieldList().stream()
                .filter(info -> !FieldStrategy.NEVER.equals(info.getInsertStrategy()))
                .forEach(info -> {
                            if (info.isLogicDelete()) {
                                valueSql.append(info.getLogicNotDeleteValue()).append(",");
                                return;
                            }
                            valueSql.append("#{item.").append(info.getProperty()).append(getTypeHandler(info)).append("},");
                        }
                );
        valueSql.delete(valueSql.length() - 1, valueSql.length());
        valueSql.append("</foreach>");
        return valueSql.toString();
    }

    private String getTypeHandler(TableFieldInfo info) {
        if (Objects.isNull(info.getTypeHandler())) {
            return "";
        }
        return ",typeHandler=".concat(info.getTypeHandler().getName());
    }
}